package com.whmall.service.crm.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.whmall.common.enumeration.VerifyEnum;
import com.whmall.common.enumeration.YesNoEnum;
import com.whmall.component.entity.dto.*;
import com.whmall.component.enumeration.*;
import com.whmall.component.service.AbstractDbService;
import com.whmall.component.util.BeanUtilsWhmall;
import com.whmall.component.util.DateUtils;
import com.whmall.component.util.FieldUtils;
import com.whmall.component.util.FlatListUtils;
import com.whmall.service.crm.entity.dto.company.*;
import com.whmall.service.crm.entity.dto.company.graph.CompanyGraphDataReqDTO;
import com.whmall.service.crm.entity.dto.company.graph.CompanyGraphDataRspDTO;
import com.whmall.service.crm.entity.dto.company.graph.node.CompanyGraphNode;
import com.whmall.service.crm.entity.dto.company.graph.node.CompanyInformationGraphNode;
import com.whmall.service.crm.enumeration.*;
import com.whmall.service.crm.module.company.convert.CompanyLogOperationRspDTO;
import com.whmall.service.crm.module.company.dao.*;
import com.whmall.service.crm.module.company.entity.*;
import com.whmall.service.crm.module.company.entity.qo.*;
import com.whmall.service.crm.module.company.service.*;
import com.whmall.service.crm.module.companybusinesslicense.dao.CompanyBusinessLicenseMapper;
import com.whmall.service.crm.module.companybusinesslicense.entity.CompanyBusinessLicenseDO;
import com.whmall.service.crm.module.companybusinesslicense.entity.qo.CompanyBusinessLicenseQO;
import com.whmall.service.crm.module.companyuser.dao.CompanyUserMapper;
import com.whmall.service.crm.module.companyuser.entity.CompanyUserDO;
import com.whmall.service.crm.module.companyuser.entity.qo.CompanyUserQO;
import com.whmall.service.crm.module.customerpool.dao.CustomerPoolLogMapper;
import com.whmall.service.crm.module.customerpool.entity.CustomerPoolLogDO;
import com.whmall.service.crm.util.ObjectValueContrastUtil;
import com.whmall.service.crm.util.PageDTOHelper;
import com.whmall.service.crm.util.PinyinUtils;
import com.whmall.service.system.module.employee.enumeration.PositionEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
@RequiredArgsConstructor
public class CompanyServiceImpl extends AbstractDbService<CompanyMapper, CompanyDO> implements CompanyService {

    private final CompanyAlgorithm companyAlgorithm;
    private final CompanyMapper companyMapper;
    private final CompanyInformationMapper companyInformationMapper;
    private final CompanyInformationService companyInformationService;
    private final CompanyBusinessLicenseMapper companyBusinessLicenseMapper;
    private final CompanyUserMapper companyUserMapper;
    private final CompanyUserInvoiceMapper companyUserInvoiceMapper;
    private final CompanyUserAddressMapper companyUserAddressMapper;
    private final CompanyAndUserApplicationMapper companyAndUserApplicationMapper;
    private final CompanyAndUserApplicationInformationMapper companyAndUserApplicationInfoMapper;
    private final CompanyAddValidator companyAddValidator;
    private final CompanyAndUserApplicationService companyAndUserApplicationService;
    private final CompanyLogMapper companyLogMapper;
    private final CompanyLogService companyLogService;
    private final CustomerPoolLogMapper customerPoolLogMapper;
    private final CompanyIndustryTypeService companyIndustryTypeService;
    private final CompanyConfigMapper companyConfigMapper;
    private final RedisTemplate<String, String> stringRedisTemplate;

    @Override
    public List<CompanyGraphDataRspDTO> findOrderDetailGraphDataByIds(List<Long> ids, CompanyGraphDataReqDTO request) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>();
        }
        if (!request.isIncludeCompanyNode()
                && !request.isIncludeCompanyInformationNode()) {
            throw new IllegalArgumentException("必须包含一项节点！");
        }
        ids = ids.stream().distinct().collect(Collectors.toList());
        List<CompanyGraphDataRspDTO> results = ids.stream()
                .map(e -> CompanyGraphDataRspDTO.builder()
                        .id(e)
                        .build())
                .collect(Collectors.toList());

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(ids);

        if (request.isIncludeCompanyNode()) {
            Map<Long, CompanyDO> companyMap = companyMapper.listBy(CompanyQO.builder()
                            .ids(ids)
                            .build())
                    .stream()
                    .collect(Collectors.toMap(CompanyDO::getId, e -> e));
            results.forEach(e -> {
                CompanyDO company = companyMap.get(e.getId());
                if (company != null) {
                    CompanyGraphNode companyGraphNode = new CompanyGraphNode();
                    BeanUtils.copyProperties(company, companyGraphNode);
                    if (companyTypeMap.containsKey(e.getId())) {
                        companyGraphNode.setCompanyType(companyTypeMap.get(e.getId()).getCompanyType());
                        companyGraphNode.setCompanyTypeList(companyTypeMap.get(e.getId()).getCompanyTypeList());
                    }
                    e.setCompany(companyGraphNode);
                }
            });
        }
        if (request.isIncludeCompanyInformationNode()) {
            Map<Long, CompanyInformationDO> companyInformationMap = companyInformationMapper.getByIds(ids)
                    .stream()
                    .collect(Collectors.toMap(CompanyInformationDO::getId, e -> e));
            results.forEach(e -> {
                CompanyInformationDO companyInformation = companyInformationMap.get(e.getId());
                if (companyInformation != null) {
                    CompanyInformationGraphNode companyInformationGraphNode = new CompanyInformationGraphNode();
                    BeanUtils.copyProperties(companyInformation, companyInformationGraphNode);
                    e.setCompanyInformation(companyInformationGraphNode);
                }
            });
        }
        return results.stream()
                .filter(e -> e.getCompany() != null
                        || e.getCompanyInformation() != null)
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyGraphNode> list(CompanyListByReqDTO reqDTO) {
        List<CompanyDO> companies = this.baseMapper.selectList(new LambdaQueryWrapper<>(CompanyDO.class)
                .like(reqDTO.getSupplierType() != null, CompanyDO::getSupplierTypeList, "-" + reqDTO.getSupplierType() + "-")
                .ge(reqDTO.getCreateTimeStart() != null, CompanyDO::getCreateTime, reqDTO.getCreateTimeStart())
                .le(reqDTO.getCreateTimeEnd() != null, CompanyDO::getCreateTime, reqDTO.getCreateTimeEnd())
                .ge(reqDTO.getFirstOrderTimeGte() != null, CompanyDO::getFirstOrderTime, reqDTO.getFirstOrderTimeGte())
                .le(reqDTO.getFirstOrderTimeLte() != null, CompanyDO::getFirstOrderTime, reqDTO.getFirstOrderTimeLte())
                .eq(reqDTO.getIsInternal() != null, CompanyDO::getIsInternal, reqDTO.getIsInternal())
                .eq(reqDTO.getIsBigCustomer() != null, CompanyDO::getIsBigCustomer, reqDTO.getIsBigCustomer())
                .eq(reqDTO.getIsLogout() != null, CompanyDO::getIsLogout, reqDTO.getIsLogout())
                .lt(reqDTO.getLastOrderTimeLt() != null, CompanyDO::getLastOrderTime, reqDTO.getLastOrderTimeLt())
        );
        return BeanUtil.copyToList(companies, CompanyGraphNode.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCompany(CompanyAddReqDTO reqDTO) {
        // 验证, 创建
        companyAddValidator.validate(reqDTO);
        CompanyDO companyDO = new CompanyDO();
        BeanUtils.copyProperties(reqDTO, companyDO);
        companyDO.setMcode(PinyinUtils.toPinyinFirstLetters(companyDO.getName()));
        // 审核通过
        companyDO.setVerified(VerifyEnum.YES.getValue());
        companyDO.setNameAbbr(FieldUtils.wrapString(companyDO.getNameAbbr()));
        // 创建者、创建时间
        companyDO.setCreateId(reqDTO.getEmployeeId());
        companyDO.setCreateTime(new Date());

        // TODO: 目前写死化学类供应商
        companyDO.setSupplierTypeList("-1-");

        CompanyInformationDO companyInformationDO = new CompanyInformationDO();
        BeanUtils.copyProperties(reqDTO, companyInformationDO);

        try {
            companyMapper.insert(companyDO);
        } catch (DuplicateKeyException e) {
            throw new IllegalArgumentException("公司中文名称或试剂商简称重复");
        }

        companyInformationDO.setId(companyDO.getId());
        companyInformationMapper.saveSelective(companyInformationDO);

        // 初始化负责人（撮合等）
        companyAlgorithm.initManagers(companyDO.getId(), reqDTO.getCandidates(),
                reqDTO.getTraderIdDefault(), reqDTO.getBdIdDefault(), reqDTO.getCsIdDefault(),
                reqDTO.getPurchaserIdDefault(), reqDTO.getVmIdDefault());
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(companyDO.getId())
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(reqDTO.getEmployeeId())
                .operationType(CompanyLogOperationTypeEnum.CREATE_COMPANY.getValue())
                .operationDesc1("新增公司")
                .createTime(new Date())
                .ip(reqDTO.getIp())
                .build();
        companyLogMapper.insertSelective(logDO);

        // 公司行业类型
        if (CollUtil.isNotEmpty(reqDTO.getCompanyTypeList())) {
            companyIndustryTypeService.saveOrUpdate(CompanyIndustryTypeCreateOrUpdateDTO.builder()
                            .typeList(reqDTO.getCompanyTypeList())
                            .companyId(companyDO.getId())
                            .build(),
                    OperatorReqDTO.builder()
                            .operatorId(reqDTO.getEmployeeId())
                            .operatorType(OperatorTypeEnum.EMPLOYEE)
                            .build());
        }
        return companyDO.getId();
    }

    @Override
    public Long syncCreateCompany(CompanySyncAddReqDTO reqDTO, OperatorReqDTO operator) {
        CompanyDO companyDO = new CompanyDO();
        BeanUtils.copyProperties(reqDTO, companyDO);
        companyDO.setMcode(PinyinUtils.toPinyinFirstLetters(companyDO.getName()));
        companyDO.setNameAbbr("@" + System.currentTimeMillis());
        // 审核通过
        companyDO.setVerified(VerifyEnum.YES.getValue());
        // 创建者、创建时间
        companyDO.setCreateId(operator.getOperatorId());
        companyDO.setCreateTime(new Date());

        // TODO: 目前写死化学类供应商
        companyDO.setSupplierTypeList("-1-");
        try {
            companyMapper.insert(companyDO);
        } catch (DuplicateKeyException e) {
            throw new IllegalArgumentException("公司中文名称或试剂商简称重复");
        }

        CompanyInformationDO companyInformationDO = new CompanyInformationDO();
        companyInformationDO.setId(companyDO.getId());
        companyInformationMapper.saveSelective(companyInformationDO);

        // 初始化负责人（撮合等）
        companyAlgorithm.initManagers(companyDO.getId(), reqDTO.getCandidates(),
                reqDTO.getTraderIdDefault(), reqDTO.getBdIdDefault(), reqDTO.getCsIdDefault(),
                reqDTO.getPurchaserIdDefault(), reqDTO.getVmIdDefault());
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(companyDO.getId())
                .createType(operator.getOperatorType().getValue())
                .createId(operator.getOperatorId())
                .operationType(CompanyLogOperationTypeEnum.CREATE_COMPANY.getValue())
                .operationDesc1("新增公司")
                .createTime(new Date())
                .ip(operator.getIp())
                .build();
        companyLogMapper.insertSelective(logDO);
        return companyDO.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Long> batchSyncCreateCompany(List<CompanySyncAddReqDTO> list, OperatorReqDTO operator) {
        if (CollUtil.isEmpty(list)) {
            return MapUtil.empty();
        }

        List<CompanyDO> companyDOList = new ArrayList<>(list.size());
        List<CompanyInformationDO> companyInformationDOList = new ArrayList<>(list.size());
        List<CompanyLogDO> companyLogDOList = new ArrayList<>(list.size());

        list.forEach(reqDTO -> {

            CompanyDO companyDO = new CompanyDO();
            BeanUtils.copyProperties(reqDTO, companyDO);
            companyDO.setMcode(PinyinUtils.toPinyinFirstLetters(companyDO.getName()));
            companyDO.setNameAbbr("@" + System.currentTimeMillis());
            // 审核通过
            companyDO.setVerified(VerifyEnum.YES.getValue());
            // 创建者、创建时间
            companyDO.setCreateId(operator.getOperatorId());
            companyDO.setCreateTime(new Date());
            // TODO: 目前写死化学类供应商
            companyDO.setSupplierTypeList("-1-");
            // 初始化负责人（撮合等）
            companyAlgorithm.newDataInitManagers(
                    companyDO, reqDTO.getCandidates(),
                    reqDTO.getTraderIdDefault(), reqDTO.getBdIdDefault(), reqDTO.getCsIdDefault(),
                    reqDTO.getPurchaserIdDefault(), reqDTO.getVmIdDefault(),
                    false);
            companyDOList.add(companyDO);

            CompanyInformationDO companyInformationDO = new CompanyInformationDO();
            companyInformationDOList.add(companyInformationDO);

            companyLogDOList.add(CompanyLogDO
                    .builder()
                    .createType(operator.getOperatorType().getValue())
                    .createId(operator.getOperatorId())
                    .operationType(CompanyLogOperationTypeEnum.CREATE_COMPANY.getValue())
                    .operationDesc1("新增公司")
                    .createTime(new Date())
                    .ip(operator.getIp())
                    .build());
        });

        if (CollUtil.isEmpty(companyDOList)) {
            return MapUtil.empty();
        }

        // 批量创建公司数据
        Map<String, Long> resultMap = new HashMap<>();
        super.saveBatch(companyDOList);
        for (int i = 0; i < companyDOList.size(); i++) {
            CompanyDO companyDO = companyDOList.get(i);
            companyInformationDOList.get(i).setId(companyDO.getId());
            companyLogDOList.get(i).setCompanyId(companyDO.getId());
            resultMap.put(list.get(0).getName(), companyDO.getId());
        }

        companyInformationService.saveBatch(companyInformationDOList);
        companyLogService.saveBatch(companyLogDOList);

        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCompany(Long companyId, CompanyAddReqDTO reqDTO) {
        Assert.notNull(companyId, "请求公司ID不能为空");
        // 验证, 创建
        companyAddValidator.validate(reqDTO);
        CompanyDO companyDO = new CompanyDO();
        BeanUtils.copyProperties(reqDTO, companyDO);
        companyDO.setMcode(PinyinUtils.toPinyinFirstLetters(companyDO.getName()));
        if (!StringUtils.hasText(reqDTO.getNameAbbr())) {
            companyDO.setNameAbbr("@" + System.currentTimeMillis());
        }
        companyDO.setId(companyId);
        // 更新者、更新时间
        companyDO.setUpdateId(reqDTO.getEmployeeId());
        companyDO.setUpdateTime(new Date());

        CompanyInformationDO companyInformationDO = new CompanyInformationDO();
        BeanUtils.copyProperties(reqDTO, companyInformationDO);
        companyInformationDO.setId(companyId);

        CompanyDO queryCompanyDO = companyMapper.selectById(companyId);
        if (queryCompanyDO == null) {
            throw new IllegalArgumentException("要更改的公司不存在");
        }

        try {
            companyMapper.updateById(companyDO);
        } catch (DuplicateKeyException e) {
            throw new IllegalArgumentException("公司中英文名称或试剂商简称重复");
        }
        CompanyInformationDO informationDO = companyInformationMapper.getById(companyInformationDO.getId());
        companyInformationMapper.updateByIdSelective(companyInformationDO);
        // 新建日志打印对比类
        CompanyLogOperationRspDTO oldLog = CompanyLogOperationRspDTO.builder()
                .name(queryCompanyDO.getName())
                .supplierOrderSpecialRequirement(informationDO.getSupplierOrderSpecialRequirement())
                .businessTrouble(informationDO.getBusinessTrouble())
                .build();
        CompanyLogOperationRspDTO newLog = CompanyLogOperationRspDTO.builder()
                .name(reqDTO.getName())
                .supplierOrderSpecialRequirement(reqDTO.getSupplierOrderSpecialRequirement())
                .businessTrouble(reqDTO.getBusinessTrouble())
                .build();
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(companyId)
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(reqDTO.getEmployeeId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(getRemark(ObjectValueContrastUtil.compareTwoClass(oldLog, newLog)))
                .createTime(new Date())
                .ip(reqDTO.getIp())
                .build();
        if (logDO.getOperationDesc1() != null && !logDO.getOperationDesc1().equals("")) {
            companyLogMapper.insertSelective(logDO);
        }
        // 公司行业类型
        if (CollUtil.isNotEmpty(reqDTO.getCompanyTypeList())) {
            companyIndustryTypeService.saveOrUpdate(CompanyIndustryTypeCreateOrUpdateDTO.builder()
                            .typeList(reqDTO.getCompanyTypeList())
                            .companyId(companyDO.getId())
                            .build(),
                    OperatorReqDTO.builder()
                            .operatorId(reqDTO.getEmployeeId())
                            .operatorType(OperatorTypeEnum.EMPLOYEE)
                            .build());
        }
    }

    @Override
    public void updateCompanyBasic(Long companyId, CompanyAddReqDTO companyAddReqDTO) {
        Assert.notNull(companyId, "请求公司ID不能为空");

        CompanyDO queryCompanyDO = companyMapper.selectById(companyId);
        Assert.notNull(null != queryCompanyDO, "要更改的公司不存在");

        CompanyDO companyDO = new CompanyDO();
        BeanUtils.copyProperties(companyAddReqDTO, companyDO);
        companyDO.setId(companyId);
        // 更新者、更新时间
        companyDO.setUpdateId(companyAddReqDTO.getEmployeeId());
        companyDO.setUpdateTime(new Date());

        CompanyInformationDO companyInformationDO = new CompanyInformationDO();
        BeanUtils.copyProperties(companyAddReqDTO, companyInformationDO);
        companyInformationDO.setId(companyId);

        CompanyInformationDO queryinfoDo = companyInformationMapper.getById(companyInformationDO.getId());
        companyInformationMapper.updateByIdSelective(companyInformationDO);

        // 新建日志打印对比类
        CompanyLogOperationRspDTO oldLog = CompanyLogOperationRspDTO.builder()
                .supplierOrderSpecialRequirement(queryinfoDo.getSupplierOrderSpecialRequirement())
                .build();
        CompanyLogOperationRspDTO newLog = CompanyLogOperationRspDTO.builder()
                .supplierOrderSpecialRequirement(companyAddReqDTO.getSupplierOrderSpecialRequirement())
                .build();
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(companyId)
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(companyAddReqDTO.getEmployeeId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(getRemark(ObjectValueContrastUtil.compareTwoClass(oldLog, newLog)))
                .createTime(new Date())
                .ip(companyAddReqDTO.getIp())
                .build();
        if (logDO.getOperationDesc1() != null && !logDO.getOperationDesc1().equals("")) {
            companyLogMapper.insertSelective(logDO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCompanyEnterpriseType(CompanyUpdateEnterpriseTypeReqDTO reqDTO, OperatorReqDTO operatorReqDTO) {

        // 更新公司信息
        CompanyDO companyDO = CompanyDO
                .builder()
                .id(reqDTO.getCompanyId())
                .hasEnterpriseCompany(reqDTO.getHasEnterpriseCompany())
                .build();
        companyMapper.updateById(companyDO);

        // 新增操作日志
        companyLogMapper.insertSelective(CompanyLogDO
                .builder()
                .companyId(reqDTO.getCompanyId())
                .createType(operatorReqDTO.getOperatorType().getValue())
                .createId(operatorReqDTO.getOperatorId())
                .operationType(CompanyLogOperationTypeEnum.HAS_ENTERPRISE_COMPANY_CHANGE.getValue())
                .operationDesc1("设置公司为" + CompanyEnterpriseCompanyTypeEnum.fromValue(reqDTO.getHasEnterpriseCompany()).getName())
                .createTime(new Date())
                .ip(operatorReqDTO.getIp())
                .build());

    }


    @Override
    public CompanyQueryRspDTO queryCompanyById(Long companyId) {

        Assert.notNull(companyId, "请求公司ID不能为空");

        CompanyDO companyDO = companyMapper.selectById(companyId);
        if (companyDO == null) {
            return null;
        }
        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(Collections.singletonList(companyId));
        CompanyInformationDO companyInformationDO = companyInformationMapper.getById(companyId);
        CompanyQueryRspDTO companyQueryRspDTO = new CompanyQueryRspDTO();

        if (companyInformationDO != null) {
            BeanUtils.copyProperties(companyInformationDO, companyQueryRspDTO);
        }
        BeanUtils.copyProperties(companyDO, companyQueryRspDTO);
        if (companyTypeMap.containsKey(companyId)) {
            companyQueryRspDTO.setCompanyType(companyTypeMap.get(companyId).getCompanyType());
            companyQueryRspDTO.setCompanyTypeList(companyTypeMap.get(companyId).getCompanyTypeList());
        }
        if (companyQueryRspDTO.getNameAbbr().indexOf("@") == 0) {
            companyQueryRspDTO.setNameAbbr(null);
        }

        // 公司经营执照
        List<CompanyBusinessLicenseDO> businessLicenseList = companyBusinessLicenseMapper.selectBy(CompanyBusinessLicenseQO.builder()
                .companyId(companyId)
                .effective(true)
                .build());
        if (CollUtil.isNotEmpty(businessLicenseList)) {
            businessLicenseList.stream()
                    .filter(b -> b.getCompanyName().equals(companyDO.getName()))
                    .findFirst()
                    .ifPresent(b -> companyQueryRspDTO.setBusinessLicenseUrl(b.getCertificateUrl()));
        }
        return companyQueryRspDTO;
    }

    @Override
    public CompanyQueryRspDTO queryCustomerInfo(Long companyId) {
        CompanyDO company = companyMapper.selectById(companyId);
        CompanyInformationDO info = companyInformationMapper.getById(companyId);
        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(Collections.singletonList(companyId));
        // 查询发票
        CompanyUserInvoiceQO qo = CompanyUserInvoiceQO.builder()
                .companyId(companyId)
                .deleted(0)
                .orderBy("default_invoice")
                .build();
        List<CompanyUserInvoiceDO> invoiceList = companyUserInvoiceMapper.listBy(qo);
        // 查询收货、票地址
        CompanyUserAddressQO companyUserAddressQO = CompanyUserAddressQO.builder()
                .companyId(companyId)
                .deleted(0)
                .orderBy("default_address")
                .build();
        List<CompanyUserAddressDO> addressList = companyUserAddressMapper.listBy(companyUserAddressQO);
        // 查询用户
        List<Long> userIds = invoiceList.stream().map(CompanyUserInvoiceDO::getUserId).collect(Collectors.toList());
        userIds.addAll(addressList.stream().map(CompanyUserAddressDO::getUserId).collect(Collectors.toList()));
        Map<Long, String> userMap = CollectionUtils.isEmpty(userIds) ? new HashMap<>(1) :
                companyUserMapper.listBy(CompanyUserQO.builder().ids(userIds).build())
                        .stream().collect(Collectors.toMap(CompanyUserDO::getId, CompanyUserDO::getName));
        // 处理发票
        List<CompanyUserInvoiceDTO> customerInvoices = invoiceList.stream().map(e -> {
            CompanyUserInvoiceDTO invoice = new CompanyUserInvoiceDTO();
            BeanUtils.copyProperties(e, invoice);
            invoice.setUserName(userMap.get(invoice.getUserId()));
            if (invoice.getDefaultInvoice() != 1) {
                invoice.setDefaultInvoice(0);
            }
            return invoice;
        }).collect(Collectors.toList());
        // 收货地址
        List<CompanyUserAddressQueryRspDTO> customerDeliveryAddress = addressList.stream()
                .filter(e ->
                        AddressTypeEnum.ADDRESS_4_DELIVERY.getValue().equals(e.getAddressType())
                ).map(e -> {
                    CompanyUserAddressQueryRspDTO address = new CompanyUserAddressQueryRspDTO();
                    BeanUtils.copyProperties(e, address);
                    address.setUserName(userMap.get(address.getUserId()));
                    if (address.getDefaultAddress() != 1) {
                        address.setDefaultAddress(0);
                    }
                    return address;
                }).collect(Collectors.toList());
        // 收票地址
        List<CompanyUserAddressQueryRspDTO> customerInvoiceAddress = addressList.stream()
                .filter(e ->
                        AddressTypeEnum.ADDRESS_4_INVOICE.getValue().equals(e.getAddressType())
                ).map(e -> {
                    CompanyUserAddressQueryRspDTO address = new CompanyUserAddressQueryRspDTO();
                    BeanUtils.copyProperties(e, address);
                    address.setUserName(userMap.get(address.getUserId()));
                    if (address.getDefaultAddress() != 1) {
                        address.setDefaultAddress(0);
                    }
                    return address;
                }).collect(Collectors.toList());
        CompanyQueryRspDTO rspDTO = new CompanyQueryRspDTO();
        BeanUtils.copyProperties(company, rspDTO);
        BeanUtils.copyProperties(info, rspDTO);
        rspDTO.setCustomerInvoices(customerInvoices);
        rspDTO.setCustomerDeliveryAddress(customerDeliveryAddress);
        rspDTO.setCustomerInvoiceAddress(customerInvoiceAddress);
        rspDTO.setCompanyType(companyTypeMap.get(companyId).getCompanyType());
        rspDTO.setCompanyTypeList(companyTypeMap.get(companyId).getCompanyTypeList());
        return rspDTO;
    }

    @Override
    public List<CompanyRspDTO> queryCompanyByIds(List<Long> ids) {

        if (StringUtils.isEmpty(ids) || ids.size() == 0) {
            return new ArrayList<>(0);
        }
        List<CompanyDO> companyDOS = companyMapper.getByIds(ids);
        Map<Long, CompanyInformationDO> companyInfos = companyInformationMapper.getByIds(ids)
                .stream().collect(Collectors.toMap(CompanyInformationDO::getId, e -> e));

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(ids);

        List<CompanyRspDTO> companyRspDTOS = new ArrayList<>();
        ids.forEach(e -> {
            for (CompanyDO companyDO : companyDOS) {
                if (e.longValue() == companyDO.getId().longValue()) {
                    CompanyRspDTO companyRspDTO = new CompanyRspDTO();
                    BeanUtils.copyProperties(companyDO, companyRspDTO);
                    companyRspDTO.setNoDevelopmentValueReason(companyInfos.containsKey(companyRspDTO.getId()) ? companyInfos.get(companyRspDTO.getId()).getNoDevelopmentValueReason() : 0);
                    companyRspDTO.setNoDevelopmentValueRemark(companyInfos.containsKey(companyRspDTO.getId()) ? companyInfos.get(companyRspDTO.getId()).getNoDevelopmentValueRemark() : "");
                    if (companyTypeMap.containsKey(companyDO.getId())) {
                        companyRspDTO.setCompanyType(companyTypeMap.get(companyDO.getId()).getCompanyType());
                        companyRspDTO.setCompanyTypeList(companyTypeMap.get(companyDO.getId()).getCompanyTypeList());
                    }
                    try {
                        BeanUtilsWhmall.converDefaultTime(companyRspDTO);
                        companyRspDTOS.add(companyRspDTO);
                    } catch (Exception ex) {
                        log.error("默认转换时间异常", ex);
                        ex.printStackTrace();
                    }
                }
            }
        });
        return companyRspDTOS;
    }

    @Override
    public Map<Long, CompanyKeyFieldDTO> listByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyMap();
        }
        ids = ids.stream().distinct().collect(Collectors.toList());
        Map<Long, CompanyInformationDO> companyInfos = companyInformationMapper.getByIds(ids)
                .stream().collect(Collectors.toMap(CompanyInformationDO::getId, e -> e));
        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(ids);

        return companyMapper.getByIds(ids)
                .stream().collect(Collectors.toMap(CompanyDO::getId, e -> {
                    log.info("supplierTypeList--" + e.getSupplierTypeList());
                    CompanyKeyFieldDTO rspDTO = new CompanyKeyFieldDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    if (companyInfos.containsKey(e.getId())) {
                        BeanUtils.copyProperties(companyInfos.get(e.getId()), rspDTO);
                    }
                    rspDTO.setNameAbbr(FieldUtils.unwrapString(e.getNameAbbr()));
                    if (companyTypeMap.containsKey(e.getId())) {
                        rspDTO.setCompanyType(companyTypeMap.get(e.getId()).getCompanyType());
                        rspDTO.setCompanyTypeList(companyTypeMap.get(e.getId()).getCompanyTypeList());
                    }
                    return rspDTO;
                }));
    }

    @Override
    public List<CompanyKeyFieldDTO> listBy(CompanyListByReqDTO reqDTO) {
        CompanyQO qo = new CompanyQO();
        BeanUtils.copyProperties(reqDTO, qo);
        List<CompanyDO> companies = companyMapper.listBy(qo);
        if (CollUtil.isEmpty(companies)) {
            return Collections.emptyList();
        }
        List<Long> companyIdList = companies.stream().map(CompanyDO::getId).collect(Collectors.toList());
        Map<Long, CompanyInformationDO> companyInfos = companyInformationMapper.getByIds(companyIdList)
                .stream()
                .collect(Collectors.toMap(CompanyInformationDO::getId, e -> e));

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(companyIdList);


        return companies.stream().map(e -> {
            CompanyKeyFieldDTO rspDTO = new CompanyKeyFieldDTO();
            BeanUtils.copyProperties(e, rspDTO);
            BeanUtils.copyProperties(companyInfos.get(e.getId()), rspDTO);
            rspDTO.setNameAbbr(FieldUtils.unwrapString(e.getNameAbbr()));
            if (companyTypeMap.containsKey(e.getId())) {
                rspDTO.setCompanyType(companyTypeMap.get(e.getId()).getCompanyType());
                rspDTO.setCompanyTypeList(companyTypeMap.get(e.getId()).getCompanyTypeList());
            }
            return rspDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Long> listByTraderId(Long id) {
        List<CompanyDO> companys = companyMapper.listBy(CompanyQO.builder().traderId(id).isLogout(0).build());
        return companys.stream().map(CompanyDO::getId).collect(Collectors.toList());
    }

    @Override
    public Map<Long, CompanyKeyFieldDTO> listAll() {

        List<CompanyDO> companyList = companyMapper.selectList(new LambdaQueryWrapper<>());
        if (CollUtil.isEmpty(companyList)) {
            return Collections.emptyMap();
        }

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(companyList.stream()
                .map(CompanyDO::getId)
                .collect(Collectors.toList()));

        return companyList
                .stream().collect(Collectors.toMap(CompanyDO::getId, e -> {
                    CompanyKeyFieldDTO rspDTO = new CompanyKeyFieldDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    if (companyTypeMap.containsKey(e.getId())) {
                        rspDTO.setCompanyType(companyTypeMap.get(e.getId()).getCompanyType());
                        rspDTO.setCompanyTypeList(companyTypeMap.get(e.getId()).getCompanyTypeList());
                    }
                    return rspDTO;
                }));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void logout(CompanyLogoutReqDTO reqDTO) {
        CompanyDO company = CompanyDO.builder()
                .id(reqDTO.getId())
                .isLogout(1)
                .logoutReason(reqDTO.getLogoutReason())
                .updateId(reqDTO.getEmployeeId())
                .updateTime(new Date())
                .build();
        int count = companyMapper.updateById(company);
        if (count != 1) {
            throw new IllegalArgumentException("未找到该公司");
        }
        if (StringUtils.hasText(reqDTO.getLogoutNote())) {
            CompanyInformationDO companyInformation = CompanyInformationDO.builder()
                    .id(reqDTO.getId())
                    .logoutNote(reqDTO.getLogoutNote())
                    .build();
            count = companyInformationMapper.updateByIdSelective(companyInformation);
            Assert.isTrue(count == 1, "未找到该公司");
        }
        String desc = "注销公司，注销原因：" +
                LogoutReasonEnum.getNameByValue(reqDTO.getLogoutReason()) +
                "，描述：" + reqDTO.getLogoutNote();
        // 公司日志
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(reqDTO.getId())
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(reqDTO.getEmployeeId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(desc)
                .ip(reqDTO.getIp()).createTime(new Date()).build();
        companyLogMapper.insertSelective(logDO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelLogout(Long id, Long employeeId) {
        CompanyDO company = CompanyDO.builder()
                .id(id)
                .isLogout(0)
                .updateId(employeeId)
                .updateTime(new Date())
                .build();
        int count = companyMapper.updateById(company);
        if (count != 1) {
            throw new IllegalArgumentException("未找到该公司");
        }
        // 公司日志
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(id)
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(employeeId)
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1("取消注销")
                .ip("").createTime(new Date()).build();
        companyLogMapper.insertSelective(logDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSupplier(Long companyId, CompanyAddReqDTO companyAddReqDTO) {
        Assert.notNull(companyId, "请求公司ID不能为空");
        // 验证, 创建
        CompanyDO companyDO = new CompanyDO();
        BeanUtils.copyProperties(companyAddReqDTO, companyDO);
        companyDO.setId(companyId);
        // 更新者、更新时间
        companyDO.setUpdateId(companyAddReqDTO.getEmployeeId());
        companyDO.setUpdateTime(new Date());

        CompanyDO companyOld = companyMapper.selectById(companyId);
        if (companyOld == null) {
            throw new IllegalArgumentException("要更改的公司不存在");
        }
        CompanyInformationDO companyInfoOld = companyInformationMapper.getById(companyId);

        try {
            companyMapper.updateById(companyDO);
        } catch (DuplicateKeyException e) {
            throw new IllegalArgumentException("公司中英文名称或试剂商简称重复");
        }
        CompanyInformationDO companyInfoDO = new CompanyInformationDO();
        BeanUtils.copyProperties(companyAddReqDTO, companyInfoDO);
        companyInfoDO.setId(companyId);
        companyInformationMapper.updateByIdSelective(companyInfoDO);
        // 公司日志
        String desc1 = !companyOld.getSupplierSettlementMethod().equals(companyDO.getSupplierSettlementMethod()) ?
                "付款方式由“" + SupplierSettlementMethodEnum.fromValue(companyOld.getSupplierSettlementMethod()).getName()
                        + "”改为“" + SupplierSettlementMethodEnum.fromValue(companyDO.getSupplierSettlementMethod()).getName() + "”"
                : "";
        String desc2 = !companyOld.getNeedDetect().equals(companyDO.getNeedDetect()) ?
                "云检测由“" + NeedDetectEnum.fromValue(companyOld.getNeedDetect()).getName()
                        + "”改为“" + NeedDetectEnum.fromValue(companyDO.getNeedDetect()).getName() + "”"
                : "";
        String desc3 = !companyOld.getIsCanMspoa().equals(companyDO.getIsCanMspoa()) ?
                "特殊供应商由“" + YesNoEnum.getMsgByCode(companyOld.getIsCanMspoa())
                        + "”改为“" + YesNoEnum.getMsgByCode(companyDO.getIsCanMspoa()) + "”"
                : "";
        String desc4 = !companyInfoOld.getMaxProductCount().equals(companyInfoDO.getMaxProductCount()) ?
                "产品上限由“" + companyInfoOld.getMaxProductCount()
                        + "”改为“" + companyInfoDO.getMaxProductCount() + "”"
                : "";
        if (StringUtils.hasText(desc1) || StringUtils.hasText(desc2) || StringUtils.hasText(desc3)
                || StringUtils.hasText(desc4)) {
            CompanyLogDO logDO = CompanyLogDO.builder()
                    .companyId(companyId)
                    .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                    .createId(companyAddReqDTO.getEmployeeId())
                    .operationType(CompanyLogOperationTypeEnum.UPDATE_SUPPLIER_INFORMATION.getValue())
                    .operationDesc1(Stream.of(desc1, desc2, desc3, desc4)
                            .filter(StringUtils::hasText)
                            .collect(Collectors.joining(" ")))
                    .ip(null).createTime(new Date()).build();
            companyLogMapper.insertSelective(logDO);
        }
    }

    @Override
    public void updateCustomer(Long id, CompanyUpdateCustomerReqDTO reqDTO) {
        if (reqDTO.getCustomerSettlementMethod() != null) {
            companyMapper.updateById(CompanyDO.builder().id(id)
                    .customerSettlementMethod(reqDTO.getCustomerSettlementMethod()).build());
        }
//        if (reqDTO.getInvoiceEmail() != null) {
//            companyInformationMapper.updateByIdSelective(
//                    CompanyInformationDO.builder().id(id)
//                            .invoiceEmail(reqDTO.getInvoiceEmail())
//                            .build());
//        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateBatch(CompanyUpdateBatchReqDTO reqDTO) {
        if (CollectionUtils.isEmpty(reqDTO.getIds())) {
            return;
        }
        if (StringUtils.hasText(reqDTO.getCustomerGrade())) {
            companyMapper.updateByIds(CompanyQO.builder().ids(reqDTO.getIds())
                    .customerGrade(reqDTO.getCustomerGrade())
                    .updateTime(new Date()).build());
        } else if (reqDTO.getIsBigCustomer() != null) {
            companyMapper.updateByIds(CompanyQO.builder().ids(reqDTO.getIds())
                    .isBigCustomer(reqDTO.getIsBigCustomer())
                    .traderId(reqDTO.getTraderId())
                    .traderDepartmentPath(reqDTO.getTraderDepartmentPath())
                    .isCustomerPoolCustomer(reqDTO.getTraderId() != null && reqDTO.getTraderId() > 0 ? 0 : null)
                    .purchaserId(reqDTO.getPurchaserId())
                    .purchaserDepartmentPath(reqDTO.getPurchaserDepartmentPath())
                    .updateId(reqDTO.getUpdateId()).updateTime(new Date()).build());
        } else if (Boolean.TRUE.equals(reqDTO.getOnlyUpdateEmployee())) {
            companyMapper.updateByIds(CompanyQO.builder().ids(reqDTO.getIds())
                    .traderId(reqDTO.getTraderId())
                    .traderDepartmentPath(reqDTO.getTraderDepartmentPath())
                    .isCustomerPoolCustomer(reqDTO.getTraderId() != null && reqDTO.getTraderId() > 0 ? 0 : null)
                    .purchaserId(reqDTO.getPurchaserId())
                    .purchaserDepartmentPath(reqDTO.getPurchaserDepartmentPath())
                    .csId(reqDTO.getCsId())
                    .csDepartmentPath(reqDTO.getCsDepartmentPath())
                    .vmId(reqDTO.getVmId())
                    .vmDepartmentPath(reqDTO.getVmDepartmentPath())
                    .controlId(reqDTO.getControlId())
                    .controlDepartmentPath(reqDTO.getControlDepartmentPath())
                    .backPurchaserId(reqDTO.getBackPurchaserId())
                    .updateId(reqDTO.getUpdateId()).updateTime(new Date()).build());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<CompanyManagerUpdateBatchRspDTO> updateManagerBatch(CompanyManagerUpdateBatchReqDTO reqDTO) {
        List<CompanyManagerUpdateBatchRspDTO> records = new LinkedList<>();
        int positionId = reqDTO.getPositionId().intValue();
        List<Long> ids = reqDTO.getIds();
        List<CompanyManagerUpdateBatchItemReqDTO> items = reqDTO.getItems();
        int startIndex = 0;
        int i = 0;
        // 按比例分配负责人
        for (CompanyManagerUpdateBatchItemReqDTO item : items) {
            i++;
            int n = Math.round((float) ids.size() * item.getRate() / 100);
            if (n > 0) {
                int endIndex = Math.min(startIndex + n, ids.size());
                endIndex = i == items.size() ? ids.size() : endIndex;
                if (startIndex < endIndex) {
                    List<Long> subIds = ids.subList(startIndex, endIndex);
                    CompanyQO qo = CompanyQO.builder()
                            .ids(subIds)
                            .updateId(reqDTO.getEmployeeId())
                            .updateTime(new Date())
                            .build();
                    if (positionId == PositionEnum.TRADER.getValue()) {
                        qo.setTraderId(item.getEmployeeId());
                        qo.setTraderDepartmentPath(item.getDepartmentPath());
                    } else if (positionId == PositionEnum.PURCHASER.getValue()) {
                        qo.setPurchaserId(item.getEmployeeId());
                        qo.setPurchaserDepartmentPath(item.getDepartmentPath());
                    } else if (positionId == PositionEnum.VENDOR_MANAGER.getValue()) {
                        qo.setVmId(item.getEmployeeId());
                        qo.setVmDepartmentPath(item.getDepartmentPath());
                    } else if (positionId == PositionEnum.CUSTOMER_SERVICE.getValue()) {
                        qo.setCsId(item.getEmployeeId());
                        qo.setCsDepartmentPath(item.getDepartmentPath());
                    } else if (positionId == PositionEnum.PURCHASER_BACK.getValue()) {
                        qo.setBackPurchaserId(item.getEmployeeId());
                    } else {
                        throw new IllegalArgumentException("不支持修改该职位");
                    }
                    companyMapper.updateByIds(qo);
                    // 记录更新
                    subIds.forEach(id -> {
                        records.add(CompanyManagerUpdateBatchRspDTO.builder()
                                .companyId(id)
                                .companyUserId(item.getEmployeeId())
                                .companyUserDepartmentPath(item.getDepartmentPath())
                                .build());
                    });
                    Map<Long, CompanyManagerUpdateReqDTO> companyMap = reqDTO.getCompanyMap();
                    if (reqDTO.getCompanyMap() != null && reqDTO.getCompanyMap().isEmpty()) {
                        subIds.forEach(e -> {
                            // 新建日志打印对比类
                            CompanyLogOperationRspDTO oldLog = new CompanyLogOperationRspDTO();
                            CompanyLogOperationRspDTO newLog = new CompanyLogOperationRspDTO();
                            if (positionId == PositionEnum.TRADER.getValue()) {
                                oldLog.setTraderName(companyMap.get(e) != null ? companyMap.get(e).getTraderName() : "");
                                newLog.setTraderName(item.getName());
                            } else if (positionId == PositionEnum.PURCHASER.getValue()) {
                                oldLog.setPurchaserName(companyMap.get(e) != null ? companyMap.get(e).getPurchaserName() : "");
                                newLog.setPurchaserName(item.getName());
                            } else if (positionId == PositionEnum.VENDOR_MANAGER.getValue()) {
                                oldLog.setVmName(companyMap.get(e) != null ? companyMap.get(e).getVmName() : "");
                                newLog.setVmName(item.getName());
                            } else if (positionId == PositionEnum.CUSTOMER_SERVICE.getValue()) {
                                oldLog.setCsName(companyMap.get(e) != null ? companyMap.get(e).getCsName() : "");
                                newLog.setCsName(item.getName());
                            } else if (positionId == PositionEnum.PURCHASER_BACK.getValue()) {
                                oldLog.setBackPurchaserName(companyMap.get(e) != null ? companyMap.get(e).getBackPurchaserName() : "");
                                newLog.setBackPurchaserName(item.getName());
                            }
                            CompanyLogDO logDO = CompanyLogDO.builder()
                                    .companyId(e)
                                    .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                                    .createId(reqDTO.getEmployeeId())
                                    .operationType(CompanyLogOperationTypeEnum.UPDATE_COMPANY_PRINCIPAL.getValue())
                                    .operationDesc1(getRemark(ObjectValueContrastUtil.compareTwoClass(oldLog, newLog)))
                                    .createTime(new Date())
                                    .ip(reqDTO.getIp())
                                    .build();
                            if (logDO.getOperationDesc1() != null && !logDO.getOperationDesc1().equals("")) {
                                companyLogMapper.insertSelective(logDO);
                            }
                        });
                    }
                    startIndex = endIndex;
                }
            }
        }
        return records;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateManager(CompanyManagerUpdateReqDTO reqDTO) {
        Date now = new Date();
        long positionId = reqDTO.getPositionId();
        CompanyDO record = CompanyDO.builder()
                .id(reqDTO.getId())
                .updateId(reqDTO.getEmployeeId())
                .updateTime(now)
                .build();
        CompanyInformationDO informationRecord = CompanyInformationDO.builder()
                .id(reqDTO.getId())
                .build();
        boolean isUpdateInformation = false;
        // 新建日志打印对比类
        CompanyLogOperationRspDTO oldLog = new CompanyLogOperationRspDTO();
        CompanyLogOperationRspDTO newLog = new CompanyLogOperationRspDTO();

        if (positionId == PositionEnum.TRADER.getValue()) {
            record.setTraderId(reqDTO.getManagerId());
            record.setTraderDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setTraderName(reqDTO.getTraderName());
            newLog.setTraderName(reqDTO.getName());
        } else if (positionId == PositionEnum.PURCHASER.getValue()) {
            record.setPurchaserId(reqDTO.getManagerId());
            record.setPurchaserDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setPurchaserName(reqDTO.getPurchaserName());
            newLog.setPurchaserName(reqDTO.getName());
        } else if (positionId == PositionEnum.VENDOR_MANAGER.getValue()) {
            record.setVmId(reqDTO.getManagerId());
            record.setVmDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setVmName(reqDTO.getVmName());
            newLog.setVmName(reqDTO.getName());
        } else if (positionId == PositionEnum.CUSTOMER_SERVICE.getValue()) {
            record.setCsId(reqDTO.getManagerId());
            record.setCsDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setCsName(reqDTO.getCsName());
            newLog.setCsName(reqDTO.getName());
        } else if (positionId == PositionEnum.PURCHASER_BACK.getValue()) {
            record.setBackPurchaserId(reqDTO.getManagerId());
            informationRecord.setHasAssignOrder(reqDTO.getHasAssignOrder());
            informationRecord.setAssignOrderThreshold(reqDTO.getAssignOrderThreshold());
            isUpdateInformation = true;
            oldLog.setBackPurchaserName(reqDTO.getBackPurchaserName());
            newLog.setBackPurchaserName(reqDTO.getName());
        } else if (positionId == PositionEnum.BD.getValue()) {
            record.setBdId(reqDTO.getManagerId());
            record.setBdDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setBdName(reqDTO.getBdName());
            newLog.setBdName(reqDTO.getName());
        } else if (positionId == PositionEnum.CONTROL.getValue()) {
            record.setControlId(reqDTO.getManagerId());
            record.setControlDepartmentPath(reqDTO.getDepartmentPath());
            oldLog.setControlName(reqDTO.getControlName());
            newLog.setControlName(reqDTO.getName());
        } else {
            throw new IllegalArgumentException("不支持修改该职位");
        }
        int count = companyMapper.updateById(record);
        Assert.isTrue(count == 1, "未找到公司");
        if (isUpdateInformation) {
            companyInformationMapper.updateByIdSelective(informationRecord);
        }
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(reqDTO.getId())
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(reqDTO.getEmployeeId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_COMPANY_PRINCIPAL.getValue())
                .operationDesc1(getRemark(ObjectValueContrastUtil.compareTwoClass(oldLog, newLog)))
                .createTime(now)
                .ip(reqDTO.getIp())
                .build();
        if (logDO.getOperationDesc1() != null && !logDO.getOperationDesc1().equals("")) {
            companyLogMapper.insertSelective(logDO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateBdBySystem(CompanyManagerUpdateReqDTO reqDTO) {

        Date now = new Date();

        // 更新公司上的Bd信息
        companyMapper.updateById(CompanyDO.builder()
                .id(reqDTO.getId())
                .bdId(reqDTO.getManagerId())
                .bdDepartmentPath(reqDTO.getDepartmentPath())
                .updateId(0L)
                .updateTime(now)
                .build());

        // 记录更新日志
        companyLogMapper.insertSelective(CompanyLogDO.builder()
                .companyId(reqDTO.getId())
                .createType(OperatorTypeEnum.SYSTEM.getValue())
                .createId(0L)
                .operationType(CompanyLogOperationTypeEnum.UPDATE_COMPANY_PRINCIPAL.getValue())
                .operationDesc1("系统更新BD为" + reqDTO.getBdName())
                .createTime(now)
                .build());
    }

    @Override
    public Integer nameExists(Long id, String name) {
        if (!StringUtils.hasText(name)) {
            return 0;
        }
        CompanyDO companyDO = companyMapper.getByName(name);
        if (companyDO == null) {
            return 0;
        }
        if (companyDO.getId().equals(id)) {
            return 0;
        }
        return 1;
    }

    @Override
    public List<CompanyListByNameRspDTO> listByName(String name, Integer companyAttribute, Integer limitNum) {
        CompanyQO qo = CompanyQO.builder().nameLike(name).orderBy("name").build();
        if (CompanyAttributeEnum.VENDOR.getValue().equals(companyAttribute)) {
            qo.setIsSupplier(1);
        } else if (CompanyAttributeEnum.CUSTOMER.getValue().equals(companyAttribute)) {
            qo.setIsCustomer(1);
        }
        PageDTOHelper.startPage(
                PageReqDTO.builder().pageNum(1).pageSize(limitNum != null ? limitNum : 10).build());
        List<CompanyDO> companies = companyMapper.listKeyFieldBy(qo);
        return companies.stream().map(e ->
                CompanyListByNameRspDTO.builder()
                        .id(e.getId())
                        .name(e.getName())
                        .traderId(e.getTraderId())
                        .hasEnterpriseCompany(e.getHasEnterpriseCompany())
                        .build()
        ).collect(Collectors.toList());
    }

    @Override
    public CompanyListByNameRspDTO getByName(String name) {
        CompanyQO qo = CompanyQO.builder().name(name).orderBy("name").build();
        List<CompanyDO> companies = companyMapper.listKeyFieldBy(qo);
        return CollUtil.isNotEmpty(companies) ? CompanyListByNameRspDTO.builder()
                .id(companies.get(0).getId())
                .name(companies.get(0).getName())
                .traderId(companies.get(0).getTraderId())
                .hasEnterpriseCompany(companies.get(0).getHasEnterpriseCompany())
                .build() : null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void employeeDepartmentPathChanged(EmployeeDepartmentPathChangedReqDTO reqDTO) {
        Long assocEmployeeId = reqDTO.getAssocEmployeeId();
        String departmentPath = reqDTO.getDepartmentPath();
        Long employeeId = reqDTO.getEmployeeId();
        Assert.isTrue(assocEmployeeId != null, "关联的员工ID必传");
        Assert.isTrue(StringUtils.hasText(departmentPath), "新部门路径必传");
        // 查询有关联的公司集合
        CompanyQO qo = CompanyQO.builder()
                .traderId(assocEmployeeId).purchaserId(assocEmployeeId)
                .vmId(assocEmployeeId).csId(assocEmployeeId)
                .build();
        List<CompanyDO> companies = companyMapper.listByAssocEmployeeId(qo);
        if (companies.size() == 0) {
            return;
        }
        // 更新撮合部门路径
        List<Long> ids = companies.stream()
                .filter(e -> assocEmployeeId.equals(e.getTraderId())
                        && !departmentPath.equals(e.getTraderDepartmentPath()))
                .map(CompanyDO::getId).collect(Collectors.toList());
        if (ids.size() > 0) {
            qo = CompanyQO.builder()
                    .ids(ids)
                    .traderDepartmentPath(departmentPath)
                    .updateId(employeeId)
                    .updateTime(new Date())
                    .build();
            companyMapper.updateByIds(qo);
        }
        // 更新采购部门路径
        ids = companies.stream()
                .filter(e -> assocEmployeeId.equals(e.getPurchaserId())
                        && !departmentPath.equals(e.getPurchaserDepartmentPath()))
                .map(CompanyDO::getId).collect(Collectors.toList());
        if (ids.size() > 0) {
            qo = CompanyQO.builder()
                    .ids(ids)
                    .purchaserDepartmentPath(departmentPath)
                    .updateId(employeeId)
                    .updateTime(new Date())
                    .build();
            companyMapper.updateByIds(qo);
        }
        // 更新供管部门路径
        ids = companies.stream()
                .filter(e -> assocEmployeeId.equals(e.getVmId())
                        && !departmentPath.equals(e.getVmDepartmentPath()))
                .map(CompanyDO::getId).collect(Collectors.toList());
        if (ids.size() > 0) {
            qo = CompanyQO.builder()
                    .ids(ids)
                    .vmDepartmentPath(departmentPath)
                    .updateId(employeeId)
                    .updateTime(new Date())
                    .build();
            companyMapper.updateByIds(qo);
        }
        // 更新客服部门路径
        ids = companies.stream()
                .filter(e -> assocEmployeeId.equals(e.getCsId())
                        && !departmentPath.equals(e.getCsDepartmentPath()))
                .map(CompanyDO::getId).collect(Collectors.toList());
        if (ids.size() > 0) {
            qo = CompanyQO.builder()
                    .ids(ids)
                    .csDepartmentPath(departmentPath)
                    .updateId(employeeId)
                    .updateTime(new Date())
                    .build();
            companyMapper.updateByIds(qo);
        }
    }

    @Override
    public Long getOneManager(Integer targetPositionId, Boolean isNewCustomer, Map<Object, Object> params, List<Long> candidates) {
        return companyAlgorithm.getOneManager(targetPositionId, isNewCustomer, params, candidates);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTime(CompanyUpdateTimeReqDTO reqDTO) {
        Assert.isTrue(reqDTO.getId() != null, "参数错误");
        CompanyDO company = companyMapper.selectById(reqDTO.getId());
        CompanyDO updateCompanyDO = new CompanyDO();
        updateCompanyDO.setId(reqDTO.getId());
        updateCompanyDO.setUpdateId(0L);
        updateCompanyDO.setUpdateTime(new Date());
        // 更新询盘相关时间
        if (reqDTO.getThisInquiryTime() != null) {
            updateCompanyDO.setPrevInquiryTime(company.getLastInquiryTime());
            updateCompanyDO.setLastInquiryTime(reqDTO.getThisInquiryTime());
            if (FieldUtils.unwrapDate(company.getFirstInquiryTime()) == null) {
                updateCompanyDO.setFirstInquiryTime(
                        FieldUtils.unwrapDate(company.getPrevInquiryTime()) != null ?
                                company.getPrevInquiryTime() :
                                FieldUtils.unwrapDate(company.getLastInquiryTime()) != null ?
                                        company.getLastInquiryTime() : reqDTO.getThisInquiryTime());
            }
            // 更新客户下单时间
        } else if (reqDTO.getThisOrderTime() != null) {
            updateCompanyDO.setPrevOrderTime(company.getLastOrderTime());
            updateCompanyDO.setLastOrderTime(reqDTO.getThisOrderTime());
            if (DateUtils.filterDate(company.getFirstOrderTime()) == null) {
                updateCompanyDO.setFirstOrderTime(reqDTO.getThisOrderTime());
            }
            // 供应商首次下单时间
        } else if (reqDTO.getThisOrderDetailTime() != null) {
            if (DateUtils.filterDate(company.getSupplierFirstOrderTime()) == null) {
                updateCompanyDO.setSupplierFirstOrderTime(reqDTO.getThisOrderDetailTime());
            }
            // 供应商首次发货时间
        } else if (reqDTO.getThisShipTime() != null) {
            if (DateUtils.filterDate(company.getSupplierFirstShipTime()) == null) {
                updateCompanyDO.setSupplierFirstShipTime(reqDTO.getThisShipTime());
            }
        }
        companyMapper.updateById(updateCompanyDO);
    }

    @Override
    public Map<Integer, List<Long>> query4TestingOrderJobHandler() {
        List<CompanyDO> companyList = companyMapper.query4TestingOrderJobHandler();
        Map<Long, String> map = companyIndustryTypeService.getTypeStrByCompanyIds(companyList.stream().map(CompanyDO::getId).collect(Collectors.toList()));

        return companyList.stream().collect(Collectors.groupingBy(
                e -> map.getOrDefault(e.getId(), "-0-").contains("-" + CompanyTypeEnum.REAGENT.getValue() + "-") ?
                        CompanyTypeEnum.REAGENT.getValue() : CompanyTypeEnum.DEFAULT.getValue(),
                Collectors.mapping(CompanyDO::getId, Collectors.toList())));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update4TestingOrderJobHandler(CompanyUpdate4TestingOrderJobHandlerReqDTO reqDTO) {
        // 不需要云检测
        if (!CollectionUtils.isEmpty(reqDTO.getCompanyIdsNoDetect())) {
            companyMapper.updateByIds(CompanyQO.builder()
                    .ids(reqDTO.getCompanyIdsNoDetect())
                    .needDetect(NeedDetectEnum.NO.getValue()).build());
            companyInformationMapper.updateByIds(CompanyInformationQO.builder()
                    .ids(reqDTO.getCompanyIdsNoDetect())
                    .detectionReason(DetectionReasonEnum.NO.getValue()).build());
        }
        // 供应商订单量小于三单
        if (!CollectionUtils.isEmpty(reqDTO.getCompanyIdsOrderNotEnough())) {
            companyMapper.updateByIds(CompanyQO.builder()
                    .ids(reqDTO.getCompanyIdsOrderNotEnough())
                    .needDetect(NeedDetectEnum.YES.getValue()).build());
            companyInformationMapper.updateByIds(CompanyInformationQO.builder()
                    .ids(reqDTO.getCompanyIdsOrderNotEnough())
                    .detectionReason(DetectionReasonEnum.ORDER_NUMBER_LT_THIRD.getValue()).build());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void fillData(CompanyFillDataReqDTO reqDTO) {
        Assert.isTrue(StringUtils.hasText(reqDTO.getName()), "参数错误");
        Long id = reqDTO.getId();
        Date now = new Date();
        // 如果公司名称是手机号，则把营业执照公司名称更新到公司上，公司名称已存在则做用户迁移
        CompanyUserDO user = companyUserMapper.getById(reqDTO.getOperator().getOperatorId());
        CompanyDO companyOld = companyMapper.selectById(reqDTO.getId());
        if (Validator.isMobile(companyOld.getName()) && !reqDTO.getName().equals(companyOld.getName())) {
            CompanyDO companyExists = companyMapper.getByName(reqDTO.getName());
            if (companyExists != null) {
                try {
                    companyUserMapper.updateByIdSelective(CompanyUserDO.builder().id(user.getId())
                            .companyId(companyExists.getId())
                            .updateTime(now).build());
                } catch (Exception e) {
                    companyUserMapper.updateByIdSelective(CompanyUserDO.builder().id(user.getId())
                            .companyId(companyExists.getId())
                            .defaultUser(FieldUtils.wrapDefault(null))
                            .updateTime(now).build());
                }
                user.setCompanyId(companyExists.getId());
                id = companyExists.getId();
            }
        }
        CompanyDO company = new CompanyDO();
        BeanUtils.copyProperties(reqDTO, company);
        company.setId(id);
        company.setMcode(PinyinUtils.toPinyinFirstLetters(company.getName()));
        company.setUpdateTime(new Date());
        companyMapper.updateById(company);
        CompanyInformationDO companyInfo = new CompanyInformationDO();
        BeanUtils.copyProperties(reqDTO, companyInfo);
        companyInfo.setId(id);
        companyInformationMapper.updateByIdSelective(companyInfo);
        // 营业执照
        if (!StringUtils.hasText(reqDTO.getSocialCreditCode())) {
            return;
        }
        List<CompanyBusinessLicenseDO> licenses = companyBusinessLicenseMapper.selectBy(
                CompanyBusinessLicenseQO.builder().companyId(id)
                        .socialCreditCode(reqDTO.getSocialCreditCode()).orderBy("id desc").build());
        if (licenses.isEmpty()) {
            companyBusinessLicenseMapper.insert(CompanyBusinessLicenseDO.builder()
                    .effective(1)
                    .companyId(id)
                    .socialCreditCode(reqDTO.getSocialCreditCode())
                    .businessEndDate(reqDTO.getBusinessEndDate())
                    .certificateUrl(reqDTO.getCertificateUrl())
                    .createTime(new Date()).build());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CompanyUpdateApplyDTO updateApply(CompanyUpdateApplyDTO reqDTO) {
        ProcessInstanceCompletedMessageReqDTO approveMessage = reqDTO.getApproveMessage();
        if (approveMessage != null) {// 审批通过/驳回
            reqDTO = (CompanyUpdateApplyDTO) companyAndUserApplicationService.finishWorkflow(approveMessage);
        }
        Long id = reqDTO.getId();
        List<CompanyAndUserApplicationDO> applications = companyAndUserApplicationMapper.selectBy(
                CompanyAndUserApplicationQO.builder().companyId(id)
                        .applicationType(CompanyAndUserApplicationTypeEnum.COMPANY_UPDATE_APPLICATION.getValue())
                        .orderBy("id desc").build());
        Assert.isTrue(applications.isEmpty()
                        || applications.get(0).getApprovalStatus() != ApprovalStatusEnum.REVIEW.getValue(),
                "有在途的申请，不能操作");
        Date now = new Date();
        CompanyUpdateApplyDTO rspDTO = new CompanyUpdateApplyDTO();
        if (approveMessage == null) {// 发起审批流
            CompanyAndUserApplicationDO application = CompanyAndUserApplicationDO.builder()
                    .applicationType(CompanyAndUserApplicationTypeEnum.COMPANY_UPDATE_APPLICATION.getValue())
                    .applicantId(reqDTO.getOperator().getOperatorId())
                    .companyId(id)
                    .userId(reqDTO.getOperator().getOperatorId())
                    .createId(reqDTO.getOperator().getOperatorId())
                    .createTime(new Date())
                    .build();
            companyAndUserApplicationMapper.insertSelective(application);
            companyAndUserApplicationInfoMapper.insertSelective(
                    CompanyAndUserApplicationInformationDO.builder()
                            .id(application.getId())
                            .applicantParam(JSONUtil.toJsonStr(reqDTO)).build());
            rspDTO.setApplicationId(application.getId());
            return rspDTO;
        }
        // 审批通过/驳回
        if (approveMessage.getApprovalStatus() != ApprovalStatusEnum.PASSED.getValue()) {
            return rspDTO;
        }
        // 审批通过
        CompanyDO company = new CompanyDO();
        BeanUtils.copyProperties(reqDTO, company);
        company.setMcode(PinyinUtils.toPinyinFirstLetters(company.getName()));
        company.setUpdateTime(now);
        companyMapper.updateById(company);
        if (reqDTO.getAddress() != null || reqDTO.getTel() != null) {
            companyInformationMapper.updateByIdSelective(CompanyInformationDO.builder().id(id)
                    .address(reqDTO.getAddress())
                    .tel(reqDTO.getTel())
                    .build());
        }


        // 营业执照
        if (!StringUtils.hasText(reqDTO.getSocialCreditCode())) {
            return rspDTO;
        }
        List<CompanyBusinessLicenseDO> licenses = companyBusinessLicenseMapper.selectBy(
                CompanyBusinessLicenseQO.builder().companyId(id)
                        .socialCreditCode(reqDTO.getSocialCreditCode()).orderBy("id desc").build());
        if (licenses.isEmpty()) {
            companyBusinessLicenseMapper.insert(CompanyBusinessLicenseDO.builder()
                    .effective(1)
                    .companyId(id)
                    .socialCreditCode(reqDTO.getSocialCreditCode())
                    .businessEndDate(reqDTO.getBusinessEndDate())
                    .certificateUrl(reqDTO.getCertificateUrl())
                    .createTime(now).build());
        }
        return rspDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePrecursorEnterpriseId(Long id, Long precursorEnterpriseId, OperatorReqDTO operatorReqDTO) {
        companyMapper.updateById(CompanyDO.builder()
                .id(id)
                .updateId(operatorReqDTO.getOperatorId())
                .updateTime(new Date())
                .build());
        companyInformationMapper.updateByIdSelective(CompanyInformationDO.builder()
                .id(id)
                .precursorEnterpriseId(precursorEnterpriseId)
                .build());
    }

    @Override
    public CompanyInformationRspDTO informationById(Long id) {
        CompanyInformationDO information = companyInformationMapper.getById(id);
        return BeanUtil.copyProperties(information, CompanyInformationRspDTO.class);
    }

    @Override
    public List<CompanyInformationRspDTO> informationByIds(List<Long> ids) {
        List<CompanyInformationDO> information = companyInformationMapper.getByIds(ids);
        return BeanUtil.copyToList(information, CompanyInformationRspDTO.class);
    }

    @Override
    public void updateCompanyInformation(CompanyInformationDTO companyInformation) {
        companyInformationMapper.updateByIdSelective(BeanUtil.copyProperties(companyInformation,
                CompanyInformationDO.class));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCustomerSettlementMethod(Long id, Integer customerSettlementMethod, OperatorReqDTO operatorReqDTO) {
        CompanyDO companyDO = companyMapper.selectById(id);
        if (!companyDO.getCustomerSettlementMethod().equals(customerSettlementMethod)) {
            companyMapper.updateById(CompanyDO.builder()
                    .id(id)
                    .customerSettlementMethod(customerSettlementMethod)
                    .updateId(operatorReqDTO.getOperatorId())
                    .updateTime(new Date())
                    .build());
            companyLogMapper.insertSelective(CompanyLogDO.builder()
                    .companyId(id)
                    .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                    .operationDesc1(String.format("客户结算方式：%s -> %s", CustomerSettlementMethodEnum.fromValue(companyDO.getCustomerSettlementMethod()).getName(),
                            CustomerSettlementMethodEnum.fromValue(customerSettlementMethod).getName()))
                    .ip(operatorReqDTO.getIp())
                    .createType(operatorReqDTO.getOperatorType().getValue())
                    .createId(operatorReqDTO.getOperatorId())
                    .createTime(new Date())
                    .build());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSupplierSettlementMethod(Long id, Integer supplierSettlementMethod, OperatorReqDTO operatorReqDTO) {
        CompanyDO companyDO = companyMapper.selectById(id);
        if (!companyDO.getSupplierSettlementMethod().equals(supplierSettlementMethod)) {
            companyMapper.updateById(CompanyDO.builder()
                    .id(id)
                    .supplierSettlementMethod(supplierSettlementMethod)
                    .updateId(operatorReqDTO.getOperatorId())
                    .updateTime(new Date())
                    .build());
            companyLogMapper.insertSelective(CompanyLogDO.builder()
                    .companyId(id)
                    .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                    .operationDesc1(String.format("供应商结算方式：%s -> %s", SupplierSettlementMethodEnum.fromValue(companyDO.getSupplierSettlementMethod()).getName(),
                            SupplierSettlementMethodEnum.fromValue(supplierSettlementMethod).getName()))
                    .ip(operatorReqDTO.getIp())
                    .createType(operatorReqDTO.getOperatorType().getValue())
                    .createId(operatorReqDTO.getOperatorId())
                    .createTime(new Date())
                    .build());
        }
    }

    @Override
    public List<CompanyKeyFieldDTO> listByPrecursorEnterpriseId(Long precursorEnterpriseId) {
        List<CompanyInformationDO> informations = companyInformationMapper.getByPrecursorEnterpriseId(precursorEnterpriseId);
        if (informations.isEmpty()) {
            return new LinkedList<>();
        }
        Map<Long, CompanyDO> companyMap = companyMapper.getByIds(informations.stream().map(CompanyInformationDO::getId)
                        .collect(Collectors.toList())).stream()
                .collect(Collectors.toMap(CompanyDO::getId, e -> e));

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(new ArrayList<>(companyMap.keySet()));

        return informations.stream().map(item -> {
            CompanyKeyFieldDTO record = BeanUtil.copyProperties(item, CompanyKeyFieldDTO.class);
            CompanyDO company = companyMap.get(record.getId());
            if (company != null) {
                BeanUtils.copyProperties(company, record);
                record.setNameAbbr(FieldUtils.unwrapString(company.getNameAbbr()));
                if (companyTypeMap.containsKey(record.getId())) {
                    record.setCompanyType(companyTypeMap.get(record.getId()).getCompanyType());
                    record.setCompanyTypeList(companyTypeMap.get(record.getId()).getCompanyTypeList());
                }
            }
            return record;
        }).collect(Collectors.toList());
    }

    public String getRemark(Map<String, List<Object>> map) {

        String remark = "";
        remark = map.entrySet().stream().map(e -> {
            String mssage = "";
            mssage = e.getKey() + "由 " + "\"" + e.getValue().get(0) + "\"" + " 更新为 " + "\"" + e.getValue().get(1) + "\"";


            return mssage;
        }).collect(Collectors.joining(","));
        return remark;

    }

    @Override
    public PageRspDTO<CompanyKeyFieldDTO> lostCustomerList(PageReqDTO pageReqDTO, LostCompanyListQueryReqDTO reqDTO) {
        CompanyQO qo = new CompanyQO();
        qo.setTraderId(reqDTO.getTraderId());
        qo.setTraderDepartmentPathPrefixLike(reqDTO.getDepartmentPath());
        qo.setLastOrderTimeGte(reqDTO.getLastOrderTimeGte());
        qo.setLastOrderTimeLte(reqDTO.getLastOrderTimeLte());
        qo.setExceptDefaultTime(YesNoEnum.YES.getCode());
        qo.setOrderBy("last_order_time");
        qo.setIsInternal(0);
        PageDTOHelper.startPage(pageReqDTO);
        List<CompanyDO> companyDOS = companyMapper.listBy(qo);
        if (CollUtil.isEmpty(companyDOS)) {
            return PageRspDTO.EMPTY;
        }

        // 公司行业类型
        Map<Long, CompanyTypeRspDTO> companyTypeMap = companyIndustryTypeService.getTypesByCompanyIds(companyDOS.stream()
                .map(CompanyDO::getId)
                .collect(Collectors.toList()));

        PageRspDTO<CompanyDO> pageRspDTO = PageDTOHelper.toPageDTO(companyDOS);
        List<CompanyKeyFieldDTO> rspDTOs = companyDOS.stream()
                .map(e -> {
                    CompanyKeyFieldDTO rspDTO = new CompanyKeyFieldDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    if (companyTypeMap.containsKey(e.getId())) {
                        rspDTO.setCompanyType(companyTypeMap.get(e.getId()).getCompanyType());
                        rspDTO.setCompanyTypeList(companyTypeMap.get(e.getId()).getCompanyTypeList());
                    }
                    return rspDTO;
                }).collect(Collectors.toList());
        return PageRspDTO.transfer(pageRspDTO, rspDTOs);
    }

    @Override
    public void relevanceCompany(CompanyRelevanceCompanyReqDTO reqDTO) {
        companyInformationMapper.updateByIdSelective(CompanyInformationDO.builder()
                .id(reqDTO.getId())
                .associatedCompanyIdList(reqDTO.getAssociatedCompanyIdList())
                .build());
        String info = "";
        if (reqDTO.isHasRelevance()) { // 关联公司
            companyMapper.updateById(CompanyDO.builder()
                    .id(reqDTO.getRelevanceCompanyId())
                    .isLockPersonalPoolCustomer(YesNoEnum.YES.getCode())
                    .build());
            info = "关联了公司";
        } else { // 取消关联
            // 当他不在有公司关联时才会进行取消关联

            // 查询这家公司是否被其他公司关联
            if (companyInformationMapper.selectAssociatedCountById(reqDTO.getRelevanceCompanyId()) == 0L) {
                // 不被任何公司关联
                companyMapper.updateById(CompanyDO.builder()
                        .id(reqDTO.getRelevanceCompanyId())
                        .isLockPersonalPoolCustomer(YesNoEnum.NO.getCode())
                        .build());
            }
            info = "取消了关联公司";
        }

        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(reqDTO.getId())
                .createType(reqDTO.getCreateType())
                .createId(reqDTO.getCreateId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(info + " (" + reqDTO.getRelevanceCompanyName() + ")")
                .createTime(new Date())
                .ip(reqDTO.getIp())
                .build();
        companyLogMapper.insertSelective(logDO);
    }

    @Override
    public void setNoDevelopmentValue(CompanyNoDevelopmentValueReqDTO reqDTO) {
        int developmentValue = YesNoEnum.NO.getCode();
        StringBuilder info = new StringBuilder();
        if (reqDTO.isHasDevelopment()) { // 设置无开发价值
            companyInformationMapper.updateByIdSelective(CompanyInformationDO.builder()
                    .id(reqDTO.getId())
                    .noDevelopmentValueReason(reqDTO.getNoDevelopmentValueReason())
                    .noDevelopmentValueRemark(reqDTO.getNoDevelopmentValueRemark())
                    .build());
            info.append("设置公司为无开发价值 原因为 ")
                    .append(Objects.requireNonNull(CustomerNoDevelopmentValueReasonEnum.fromValue(reqDTO.getNoDevelopmentValueReason())).getName());
            if (StrUtil.isNotBlank(reqDTO.getNoDevelopmentValueRemark())) {
                info.append("; 特殊情况说明为：")
                        .append(reqDTO.getNoDevelopmentValueRemark());
            }

        } else { // 恢复开发价值
            developmentValue = YesNoEnum.YES.getCode();
            companyInformationMapper.updateByIdSelective(CompanyInformationDO.builder()
                    .id(reqDTO.getId())
                    .noDevelopmentValueReason(YesNoEnum.NO.getCode())
                    .noDevelopmentValueRemark("")
                    .build());
            info.append("恢复开发价值");
        }
        companyMapper.updateById(CompanyDO.builder()
                .id(reqDTO.getId())
                .isDevelopmentValue(developmentValue)
                .build());


        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(reqDTO.getId())
                .createType(reqDTO.getCreateType())
                .createId(reqDTO.getCreateId())
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(info.toString())
                .createTime(new Date())
                .ip(reqDTO.getIp())
                .build();

        customerPoolLogMapper.insertSelective(
                CustomerPoolLogDO.builder()
                        .companyId(reqDTO.getId())
                        .operationType(developmentValue == 0 ? CustomerPoolOperationTypeEnum.NO_DEVELOPMENT_VALUE.getValue()
                                : CustomerPoolOperationTypeEnum.RESTORE_DEVELOPMENT_VALUE.getValue())
                        .remark(developmentValue == 0 ? info.toString() : "")
                        .handleType(reqDTO.getCreateType())
                        .handleId(reqDTO.getCreateId())
                        .handleTime(new Date()).build()
        );

        companyLogMapper.insertSelective(logDO);

    }

    @Override
    public List<Long> listByTraderDepartment(String departmentPath) {
        List<CompanyDO> companies = companyMapper.listBy(CompanyQO.builder()
                .traderDepartmentPathPrefixLike(departmentPath)
                .isLogout(0).build());
        return companies.stream().map(CompanyDO::getId).collect(Collectors.toList());
    }

    @Override
    public List<Long> listByTraderDepartmentPath(String departmentPath) {
        return this.lambdaQuery()
                .select(CompanyDO::getId)
                .eq(CompanyDO::getTraderDepartmentPath, departmentPath)
                .eq(CompanyDO::getIsLogout, 0)
                .list().stream().map(CompanyDO::getId).collect(Collectors.toList());
    }

    @Override
    public List<CompanyNoTypeRspDTO> listNoCompanyTypeCustomerList() {
        return companyMapper.listNoCompanyTypeCustomerList();
    }

    @Override
    public Long companyBasicInfoApply(CompanyBasicInfoApplyDTO basicInfoApplyDTO, OperatorReqDTO operator) {

        // 公司基本信息审核中的申请
        List<CompanyAndUserApplicationDO> applicationList = companyAndUserApplicationMapper.selectBy(CompanyAndUserApplicationQO.builder()
                .companyId(basicInfoApplyDTO.getId())
                .applicationType(CompanyAndUserApplicationTypeEnum.COMPANY_BASIC_APPLICATION.getValue())
                .approvalStatus(ApprovalStatusEnum.REVIEW.getValue())
                .build());
        Assert.isTrue(CollUtil.isEmpty(applicationList), "有在途的申请，不能操作");

        // 保存申请信息
        CompanyAndUserApplicationDO application = CompanyAndUserApplicationDO.builder()
                .applicationType(CompanyAndUserApplicationTypeEnum.COMPANY_BASIC_APPLICATION.getValue())
                .applicantId(operator.getOperatorId())
                .companyId(basicInfoApplyDTO.getId())
                .userId(operator.getOperatorId())
                .createId(operator.getOperatorId())
                .createTime(new Date())
                .build();
        companyAndUserApplicationMapper.insertSelective(application);
        companyAndUserApplicationInfoMapper.insertSelective(
                CompanyAndUserApplicationInformationDO.builder()
                        .id(application.getId())
                        .applicantParam(JSONUtil.toJsonStr(basicInfoApplyDTO))
                        .build());

        return application.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void companyBasicInfoAudit(ProcessInstanceCompletedMessageReqDTO finishMessage) {

        // 更新申请的审核状态
        CompanyBasicInfoApplyDTO apply = (CompanyBasicInfoApplyDTO) companyAndUserApplicationService.finishWorkflow(finishMessage);

        // 审核驳回
        if (finishMessage.getApprovalStatus() != ApprovalStatusEnum.PASSED.getValue()) {
            return;
        }

        // 审核通过
        // 更新公司基本信息
        CompanyDO companyDO = BeanUtil.copyProperties(apply, CompanyDO.class);
        super.baseMapper.updateById(companyDO);

        // 更新公司其他信息
        CompanyInformationDO companyInformationDO = BeanUtil.copyProperties(apply, CompanyInformationDO.class);
        companyInformationMapper.updateByIdSelective(companyInformationDO);

        // 更新公司行业信息
        companyIndustryTypeService.saveOrUpdate(CompanyIndustryTypeCreateOrUpdateDTO.builder()
                        .companyId(apply.getId())
                        .typeList(apply.getTypeList())
                        .build(),
                OperatorReqDTO.SYSTEM);

        if (StringUtils.hasText(apply.getBusinessLicenseUrl())) {

            // 更新公司营业执照信息(唯一营业执照 直接更新 否则根据名字匹配更新)
            List<CompanyBusinessLicenseDO> licenseList = companyBusinessLicenseMapper.selectBy(CompanyBusinessLicenseQO.builder()
                    .companyId(apply.getId())
                    .effective(true)
                    .build());

            Long licenseId = null;

            if (CollUtil.isNotEmpty(licenseList)) {

                if (licenseList.size() == 1) {
                    licenseId = licenseList.get(0).getId();
                } else if (licenseList.stream().anyMatch(l -> l.getCompanyName().equals(apply.getName()))) {
                    licenseId = licenseList.stream().filter(l -> l.getCompanyName().equals(apply.getName())).findFirst().get().getId();
                }

                if (null != licenseId) {
                    companyBusinessLicenseMapper.update(CompanyBusinessLicenseDO.builder()
                            .id(licenseId)
                            .certificateUrl(apply.getBusinessLicenseUrl())
                            .updateTime(new Date())
                            .build());
                }
            }
        }
    }

    @Override
    public void updateLock(Long companyId, OperatorReqDTO operator) {
        CompanyDO company = this.getById(companyId);
        cn.hutool.core.lang.Assert.isFalse(company == null, "公司不存在");
        CompanyDO companyDO = new CompanyDO();
        companyDO.setId(companyId);
        companyDO.setIsLockPersonalPoolCustomer(company.getIsLockPersonalPoolCustomer().equals(0) ? 1 : 0);
        companyDO.setUpdateId(operator.getOperatorId());
        companyDO.setUpdateTime(new Date());
        this.updateById(companyDO);
    }

    @Override
    public List<List<Long>> getCompanyAssociatedList(List<Long> companyIdList) {

        List<CompanyInformationDO> companyInfoList = companyInformationMapper.getByIds(companyIdList);
        if (CollUtil.isEmpty(companyInfoList)) {
            return Collections.emptyList();
        }

        return companyInfoList.stream()
                .map(c -> {
                    List<Long> idList = FieldUtils.unwrapArray(c.getAssociatedCompanyIdList(), "-", Long.class);
                    idList.add(c.getId());
                    return idList;
                }).collect(Collectors.toList());
    }

    @Override
    public Map<Long, Long> getAllParentCompany() {
        Map<Long, Long> data = new HashMap<>();
        // 性能不好弃用，关联公司数据量非常少（200条左右），改为查询全部
        // 对ID物理分页，防止sql过长(最好的方式是修改表结构，关联公司通过一张表来处理)
//        CommonUtils.listPage(childrenCompanyIds, 5000)
//                .forEach(ids -> companyInformationMapper.getByChildrenCompanyIds(ids)
//                        .forEach(companyInfo -> FlatListUtils.toList(companyInfo.getAssociatedCompanyIdList(), Long::valueOf)
//                                .forEach(childrenCompanyId -> data.put(childrenCompanyId, companyInfo.getId()))));
        companyInformationMapper.getAllAssociateCompany()
                .forEach(companyInfo -> FlatListUtils.toList(companyInfo.getAssociatedCompanyIdList(), Long::valueOf)
                        .forEach(childrenCompanyId -> data.put(childrenCompanyId, companyInfo.getId())));
        return data;
    }

    @Override
    public List<Long> listByPurchaserInfo(Long purchaserId, String purchaserDepartmentPath) {
        List<CompanyDO> companys = companyMapper.listBy(CompanyQO.builder().purchaserId(purchaserId).purchaserDepartmentPath(purchaserDepartmentPath).isLogout(0).build());
        return companys.stream().map(CompanyDO::getId).collect(Collectors.toList());
    }

    @Override
    public PageRspDTO<CompanyKeyFieldDTO> pageWithRegister(PageReqDTO pageReqDTO, CountWithRegisterReqDTO condition) {
        Page<CompanyDO> companyPage = this.page(new Page<>(pageReqDTO.getPageNum(), pageReqDTO.getPageSize()), buildQueryWrapper(condition));
        return new PageRspDTO<>(
                (int) companyPage.getCurrent(),
                (int) companyPage.getSize(),
                (int) companyPage.getPages(),
                (int) companyPage.getTotal(),
                companyPage.getRecords().stream()
                        .map(e -> BeanUtil.copyProperties(e, CompanyKeyFieldDTO.class))
                        .collect(Collectors.toList())
        );
    }

    @Override
    public Long countWithRegister(CountWithRegisterReqDTO condition) {
        return this.count(buildQueryWrapper(condition));
    }

    /**
     * 修改是否能查看AI路线设免费版
     *
     * @param companyId 单位id
     */
    @Override
    public void updateCvfvairById(Long companyId, Integer hasCvfvair, OperatorReqDTO operator) {
        companyMapper.updateById(CompanyDO.builder().id(companyId).hasCvfvair(hasCvfvair).build());
        String desc = hasCvfvair.equals(1) ? "打开" : "关闭";
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(companyId)
                .createType(OperatorTypeEnum.EMPLOYEE.getValue())
                .createId(operator.getOperatorId())
                .operationType(CompanyLogOperationTypeEnum.PC_SETTING.getValue())
                .operationDesc1(desc + "是否在PC端个人中心显示\"路线设计（原）\"入口")
                .createTime(new Date())
                .ip(operator.getIp())
                .build();
        companyLogMapper.insertSelective(logDO);

    }

    private QueryWrapper<CompanyDO> buildQueryWrapper(CountWithRegisterReqDTO condition) {
        Long traderId = condition.getTraderId();
        String traderDepartmentPath = condition.getTraderDepartmentPath();
        if (Boolean.TRUE.equals(condition.getIsHead()) || Boolean.TRUE.equals(condition.getIsRoot())) {
            if (condition.getReferenceTraderId() != null) {
                traderId = condition.getReferenceTraderId();
            }
            if (StrUtil.isNotBlank(condition.getReferenceTraderDepartmentPath())) {
                traderDepartmentPath = condition.getReferenceTraderDepartmentPath();
            }
        }
        Long finalTraderId = traderId;
        String finalTraderDepartmentPath = traderDepartmentPath;
        return new QueryWrapper<CompanyDO>()
                .ge(condition.getCreateTimeStart() != null, "create_time", condition.getCreateTimeStart())
                .le(condition.getCreateTimeEnd() != null, "create_time", condition.getCreateTimeEnd())
                .eq("verified", 1)
                .and(traderId != null, (e) ->
                        e.eq("trader_id", finalTraderId)
                                .or().eq("trader_id", 0))
                .and(StrUtil.isNotBlank(traderDepartmentPath), e ->
                        e.likeRight("trader_department_path", finalTraderDepartmentPath)
                                .or().eq("trader_id", 0));
    }

    @Override
    public List<Long> selectByIdsShareLock(List<Long> ids) {
        return companyMapper.selectByIdsShareLock(ids);
    }

    @Override
    @Transactional
    public void setBillingBlackList(Long id, Integer inBillingBlacklist, String comment, OperatorReqDTO operatorReqDTO) {
        companyMapper.updateById(CompanyDO.builder()
                .id(id)
                .inBillingBlacklist(inBillingBlacklist)
                .updateId(operatorReqDTO.getOperatorId())
                .updateTime(new Date())
                .build());
        String operationDesc;
        if (inBillingBlacklist.equals(0)) {
            operationDesc = "移除客户为账期黑名单";
        } else {
            operationDesc = "添加客户为账期黑名单，原因为：" + comment;
        }
        CompanyLogDO logDO = CompanyLogDO.builder()
                .companyId(id)
                .operationType(CompanyLogOperationTypeEnum.UPDATE_BASIC_INFORMATION.getValue())
                .operationDesc1(operationDesc)
                .ip(operatorReqDTO.getIp())
                .createType(operatorReqDTO.getOperatorType().getValue())
                .createId(operatorReqDTO.getOperatorId())
                .createTime(new Date())
                .build();
        companyLogMapper.insertSelective(logDO);
    }

    @Override
    public List<CompanyInformationRspDTO> findAssociatedCompany(Long id) {
        List<CompanyInformationDO> byChildrenCompanyIds = companyInformationMapper.getByChildrenCompanyIds(Arrays.asList(id));
        return BeanUtil.copyToList(byChildrenCompanyIds, CompanyInformationRspDTO.class);
    }

    @Override
    @Transactional
    public void updateCcp(Long id, UpdateCcpReqDto reqDto, OperatorReqDTO operatorReqDTO) {
        companyMapper.updateById(CompanyDO.builder()
                .id(id)
                .ccpId(reqDto.getCcpId())
                .ccpDepartmentPath(reqDto.getCcpDepartmentPath())
                .updateId(operatorReqDTO.getOperatorId())
                .updateTime(new Date())
                .build());
        companyLogMapper.insert(CompanyLogDO.builder()
                .companyId(id)
                .operationType(CompanyLogOperationTypeEnum.UPDATE_COMPANY_PRINCIPAL.getValue())
                .operationDesc1(String.format("修改客户专属采购 %s -> %s", reqDto.getOldCcpName(), reqDto.getNewCcpName()))
                .createId(operatorReqDTO.getOperatorId())
                .createType(operatorReqDTO.getOperatorType().getValue())
                .createTime(new Date())
                .ip(operatorReqDTO.getIp())
                .build());
    }

    @Override
    public OrderTradingEntityRspDto getOrderTradingEntities(OrderTradingEntityReqDto reqDto) {
        // 可选交易主体
        List<Long> optionalList = companyConfigMapper.selectList(new QueryWrapper<CompanyConfigDO>().lambda()
                        .eq(CompanyConfigDO::getKey, CompanyConfigKeyEnum.HAS_USE_ORDER_TRADE_SUBJECT.getName())
                        .eq(CompanyConfigDO::getValue, "1")).stream()
                .map(CompanyConfigDO::getCompanyId)
                .collect(Collectors.toList());
        OrderTradingEntityRspDto rspDto = new OrderTradingEntityRspDto().setOptionalList(optionalList);
        String redisKey;
        if (Boolean.TRUE.equals(reqDto.getIsOverseas())) {
            redisKey = "overseas";
        } else if (Boolean.TRUE.equals(reqDto.getIsOrderCategoryB())) {
            redisKey = "order_category_b";
        } else if (Boolean.TRUE.equals(reqDto.getIsPrecursor())) {
            redisKey = "precursor";
        } else {
            redisKey = reqDto.getCustomerCompanyId().toString();
        }
        Object redisValue = stringRedisTemplate.opsForHash().get("$dict$customer_internal_company", redisKey);
        if (redisValue == null) {
            redisValue = stringRedisTemplate.opsForHash().get("$dict$customer_internal_company", "*");
        }
        JSONObject jsonObject = JSONUtil.parseObj(redisValue.toString());
        rspDto.setDefaultId(jsonObject.get("default", Long.class));
        return rspDto;
    }
}
